﻿using BaseMsg;
using CoreMsg;
using ProtoBuf;
using System;
using System.IO;

namespace K.Client
{
    public class MsgFactory
    {
        static KProtobufSerializer serializer = new KProtobufSerializer();

        public static Msg Create(int msgID, IExtensible body, long roleID = 0, long DstConnID = 0)
        {
            var msg = new Msg();
            msg.id = msgID;
            var head = new MsgHead();
            head.MsgID = msgID;
            head.DstID = DstConnID;
            head.RoleID = roleID;
            msg.head = head;
            msg.body = body;
            return msg;
        }

        public static Msg Create(int msgID, IExtensible body, MsgHead head)
        {
            var msg = new Msg();
            msg.id = msgID;
            head.MsgID = msgID;
            msg.head = head;
            msg.body = body;
            return msg;
        }

        public static byte[] SerializePBMsg<T>(T msg)
        {
            var ms = new MemoryStream();
            serializer.Serialize(ms, msg);
            var re = ms.ToArray();
            return re;
        }

        public static byte[] SerializeHead(Msg msg)
        {
            return SerializePBMsg(msg.head as MsgHead);
        }

        public static bool DeserializeHead(Msg msg, MemoryStream ms)
        {
            msg.head = serializer.Deserialize(ms, null, typeof(MsgHead)) as MsgHead;
            msg.id = (msg.head as MsgHead).MsgID;
            return true;
        }

        public static byte[] SerializeBody(Msg msg)
        {
            switch (msg.id)
            {
                //todo 1.在这里添加消息序列化
                //核心消息
                case (int)CORE_MSG_ID.ID_S2D_EXECUTESQL_REQUEST: return SerializePBMsg(msg.body as MsgExecuteSqlRequest);
                case (int)CORE_MSG_ID.ID_D2S_EXECUTESQL_RESPONSE: return SerializePBMsg(msg.body as MsgExecuteSqlResponse);
                case (int)CORE_MSG_ID.ID_S2S_GET_ROLEID_IN_PLANE_REQUEST: return SerializePBMsg(msg.body as MsgGetRoleIDInPlaneRequest);
                case (int)CORE_MSG_ID.ID_S2S_GET_ROLEID_IN_PLANE_RESPONSE: return SerializePBMsg(msg.body as MsgGetRoleIDInPlaneResponse);
                case (int)CORE_MSG_ID.ID_S2S_SYN_ROLEID_TO_PLANE_REQUEST: return SerializePBMsg(msg.body as MsgSynRoleIDToPlaneRequest);
                default:
                    {
                        Console.WriteLine("SerializeBody error,{0}({1})-->{2}({3}),msgID:{4}(0x{4:X8})", msg.head.SrcEntity, msg.head.SrcID, msg.head.DstEntity, msg.head.DstID, msg.id);
                        return null;
                    }
            }
        }

        public static bool DeserializeBody(Msg msg, MemoryStream ms)
        {
            try
            {
                switch (msg.id)
                {
                    //todo 2.在这里添加消息反序列化
                    //核心消息
                    case (int)CORE_MSG_ID.ID_S2D_EXECUTESQL_REQUEST: { msg.body = serializer.Deserialize(ms, null, typeof(MsgExecuteSqlRequest)) as MsgExecuteSqlRequest; break; }
                    case (int)CORE_MSG_ID.ID_D2S_EXECUTESQL_RESPONSE: { msg.body = serializer.Deserialize(ms, null, typeof(MsgExecuteSqlResponse)) as MsgExecuteSqlResponse; break; }
                    case (int)CORE_MSG_ID.ID_S2S_GET_ROLEID_IN_PLANE_REQUEST: { msg.body = serializer.Deserialize(ms, null, typeof(MsgGetRoleIDInPlaneRequest)) as MsgGetRoleIDInPlaneRequest; break; }
                    case (int)CORE_MSG_ID.ID_S2S_GET_ROLEID_IN_PLANE_RESPONSE: { msg.body = serializer.Deserialize(ms, null, typeof(MsgGetRoleIDInPlaneResponse)) as MsgGetRoleIDInPlaneResponse; break; }
                    case (int)CORE_MSG_ID.ID_S2S_SYN_ROLEID_TO_PLANE_REQUEST: { msg.body = serializer.Deserialize(ms, null, typeof(MsgSynRoleIDToPlaneRequest)) as MsgSynRoleIDToPlaneRequest; break; }
                    default:
                        {
                            Console.WriteLine("DeserializeBody failed,unregistered msg, {0}({1})-->{2}({3}),msgID:{4}(0x{4:X8})", msg.head.SrcEntity, msg.head.SrcID, msg.head.DstEntity, msg.head.DstID, msg.id);
                            return false;
                        }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("DeserializeBody failed,msg content err,{0}({1})-->{2}({3}),msgID:{4}(0x{4:X8})", msg.head.SrcEntity, msg.head.SrcID, msg.head.DstEntity, msg.head.DstID, msg.id);
                return false;
            }
            return true;
        }

        //todo 可以考虑用反射来序列化和反序列化，这样只需要注册一次
        static Type GetMsgType(int nMsgID)
        {
            switch (nMsgID)
            {
                default:
                    {
                        return null;
                    }
            }
        }
    }
}